/******************************************************************************
 * @file    Charlieplexing_hal.c
 * @author  赵子恒 3393018959@qq.com 公众号：子恒笔记
 * @version V1.0
 * @date    2025-05-06
 * @brief   Charlieplexing HAL implementation for PY32F030xx.
 ******************************************************************************
 ******************************************************************************
 */
#include "Charlieplexing_hal.h"

hal_charlieplexing_gpio_map_t gpio_map[HAL_GPIO_ID_MAX] = HAL_GPIO_MAP;
hal_charlieplexing_id_map_t id_map[] = HAL_ID_MAP;

//初始化所有gpio
void hal_charlieplexing_init(void)
{
    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    HAL_CHARLIEPLEXING_ALL_CLK_EN();
    for (uint8_t i = 0; i < HAL_GPIO_ID_MAX; i++)
    {
        GPIO_InitStruct.Pin = gpio_map[i].Pin;
        GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
        GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
        GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
        LL_GPIO_Init(gpio_map[i].GPIOx, &GPIO_InitStruct);
    }
}

//单独点亮或熄灭某一个led，用于单颗循环扫描
//单颗循环扫描亮度均匀，如果led压降不一致，也能相对较好的工作，缺点是led灯数多了，亮度则会较低
//适合小数量的led扫描
void hal_charlieplexing_led_id_set(uint8_t led_id, led_mode_enum_t mode)
{
    if (led_id >= HAL_LED_ID_MAX)
        return;
	
	hal_charlieplexing_gpio_map_t *gpio_higt = &gpio_map[id_map[led_id].gpio_high_id];
	hal_charlieplexing_gpio_map_t *gpio_low = &gpio_map[id_map[led_id].gpio_low_id];
	
    if (mode == LED_ON)
    {
		LL_GPIO_SetOutputPin(gpio_higt->GPIOx, gpio_higt->Pin);
        LL_GPIO_ResetOutputPin(gpio_low->GPIOx, gpio_low->Pin);
        LL_GPIO_SetPinMode(gpio_higt->GPIOx, gpio_higt->Pin, LL_GPIO_MODE_OUTPUT);
        LL_GPIO_SetPinMode(gpio_low->GPIOx, gpio_low->Pin, LL_GPIO_MODE_OUTPUT);
    }
    else
    {
        LL_GPIO_SetPinMode(gpio_higt->GPIOx, gpio_higt->Pin, LL_GPIO_MODE_ANALOG);
        LL_GPIO_SetPinMode(gpio_low->GPIOx, gpio_low->Pin, LL_GPIO_MODE_ANALOG);
    }
}


void hal_charlieplexing_gpio_all_highz(void)
{
	for (uint8_t i = 0; i < HAL_GPIO_ID_MAX; i++)
    {
        LL_GPIO_SetPinMode(gpio_map[i].GPIOx, gpio_map[i].Pin, LL_GPIO_MODE_ANALOG);
    }
}

//传入gpio id编号，设置对应状态
void hal_charlieplexing_gpio_id_set(hal_gpio_id_t gpio_id, gpio_mode_enum_t mode)
{
	if (gpio_id >= HAL_GPIO_ID_MAX)
        return;
	
	hal_charlieplexing_gpio_map_t *gpio_io = &gpio_map[gpio_id];
	
    if (mode == OUTPUT_1)
    {
		LL_GPIO_SetOutputPin(gpio_io->GPIOx, gpio_io->Pin);
        LL_GPIO_SetPinMode(gpio_io->GPIOx, gpio_io->Pin, LL_GPIO_MODE_OUTPUT);
    }
    else if (mode == OUTPUT_0)
    {
		LL_GPIO_ResetOutputPin(gpio_io->GPIOx, gpio_io->Pin);
        LL_GPIO_SetPinMode(gpio_io->GPIOx, gpio_io->Pin, LL_GPIO_MODE_OUTPUT);
    }else
    {
        LL_GPIO_SetPinMode(gpio_io->GPIOx, gpio_io->Pin, LL_GPIO_MODE_ANALOG);
    }
}

//传入led id，判断该led的阴极gpio id是否为gpio_low_id,若是，则返回该led id对应的阳极gpio id
//否则返回HAL_GPIO_ID_MAX
hal_gpio_id_t hal_find_com_low_gpio_id(hal_gpio_id_t gpio_low_id, uint8_t led_id)
{
	if (led_id >= HAL_LED_ID_MAX)
        return HAL_GPIO_ID_MAX;
	
	if(gpio_low_id != id_map[led_id].gpio_low_id)
		return HAL_GPIO_ID_MAX;

	return id_map[led_id].gpio_high_id;
}

//传入led id，判断该led的阳极gpio id是否为gpio_higt_id,若是，则返回该led id对应的阴极gpio id
hal_gpio_id_t hal_find_com_higt_gpio_id(hal_gpio_id_t gpio_higt_id, uint8_t led_id)
{
	if (led_id >= HAL_LED_ID_MAX)
        return HAL_GPIO_ID_MAX;
	
	if(gpio_higt_id != id_map[led_id].gpio_high_id)
		return HAL_GPIO_ID_MAX;

	return id_map[led_id].gpio_low_id;
}

